#include <iostream>
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include "palmdll.h"

using namespace std;
using namespace cv;

IplImage *myGetClearPalmArea(IplImage *thImg);
IplImage *getROI(IplImage *imgInput, bool showDebugInfo);

char *inPath1 = "./IMG_0161_010_LLL_.jpg"; //图片1路径
char *inPath2 = "./IMG_0161_011_LLL_.jpg"; //图片2路径

int main(int argc, char **argv)
{
	IplImage *imgInput1 = cvLoadImage(inPath1, 0); //加载图像
	IplImage *imgInput2 = cvLoadImage(inPath2, 0);

	if (imgInput1 == NULL || imgInput2 == NULL)
	{
		cout << "Load Image error!" << endl;
		exit(0);
	}

	//ROI提取
	IplImage *roi1 = getROI(imgInput1, true); //false -> true 可以查看中间过程图像
	IplImage *roi2 = getROI(imgInput2, false);

	if (roi1 == NULL || roi2 == NULL)
	{
		cout << "roi extraction error!" << endl;
		exit(0);
	}

	cvSaveImage("./roi1.bmp", roi1); //保存图像
	cvSaveImage("./roi2.bmp", roi2); //保存图像

	//----------------------------------------------------------------
	printFeature feat1, feat2;
	FeatureExtractionPrint((uchar *)roi1->imageData, &feat1); //特征提取
	FeatureExtractionPrint((uchar *)roi2->imageData, &feat2); //特征提取

	float score = -1; //匹配得分
	score = MatchPrint(&feat1, &feat2);
	float TH = 0.35;

	if (score < TH) //结果
		cout << "same :)" << endl
			 << endl;
	else
		cout << "different :(" << endl
			 << endl;

	return 0;
}

IplImage *getROI(IplImage *imgInput, bool showDebugInfo)
{
	IplImage *imgTh = cvCloneImage(imgInput);			  //二值化图像
	cvThreshold(imgInput, imgTh, 0, 255, CV_THRESH_OTSU); //二值化
	// cv::Mat img(cv::Size2d(imgInput->width, imgInput->height), CV_8U);
	// img.data = (uchar *)imgTh->imageData;
	// cv::imshow("img", img);
	// cv::waitKey(0);
	cvDilate(imgTh, imgTh, 0, 2); //膨胀
	cvErode(imgTh, imgTh, 0, 2);  //腐蚀 2
	//-------------------------------------

	IplImage *imgPalm = cvCreateImage(cvSize(320, 240), 8, 1);   //标准手掌图像
	IplImage *imgBinary = cvCreateImage(cvSize(320, 240), 8, 1); //二值化手掌区域
	cvResize(imgInput, imgPalm);
	cvResize(imgTh, imgBinary);

	IplImage *imgPalmArea = myGetClearPalmArea(imgBinary); //最终的手掌区域
	IplImage *roi = cvCreateImage(cvSize(128, 128), 8, 1); //roi 图像

	uchar *palmData = (uchar *)imgPalm->imageData;   //获得手掌图像数据
	uchar *thData = (uchar *)imgPalmArea->imageData; //
	uchar *roiData = (uchar *)roi->imageData;		 //

	int Sx[4], Sy[4]; //ROI坐标

	int ret = Lnpreprocessing(palmData, thData, roiData, Sx, Sy); //图像预处理

	if (!ret) //出错返回
	{
		cout << "preprocessing error!" << endl;
		return 0;
	}

	printf("The input image has beed resized to320x240\n up :(x,y): %d, %d \ndown:(x,y): %d, %d\n", holeList[0][lastP1Index][0], holeList[0][lastP1Index][1], holeList[1][lastP2Index][0], holeList[1][lastP2Index][1]);
	//debug
	Point2d p1(holeList[0][lastP1Index][0], holeList[0][lastP1Index][1]);
	Point2d p2(holeList[1][lastP2Index][0], holeList[1][lastP2Index][1]);
	cvCircle(imgPalm, p1, 5, cvScalar(255, 0, 0));
	cvCircle(imgPalm, p2, 5, cvScalar(255, 0, 0));
	cvShowImage("imgPalm", imgPalm);
	cvWaitKey(0);

	if (showDebugInfo)
	{
		cvShowImage("inputImg", imgInput);
		cvShowImage("thImg", imgTh);	 //输入手掌图像
		cvShowImage("imgPalm", imgPalm); //手掌
		cvShowImage("imgBinary", imgBinary);
		cvShowImage("imgPalmArea", imgPalmArea); //手掌区域
		cvShowImage("roi", roi);				 //roi
		cvWaitKey(0);
	}

	cvReleaseImage(&imgTh);
	cvReleaseImage(&imgPalm);
	cvReleaseImage(&imgBinary);
	cvReleaseImage(&imgPalmArea);
	return roi;
}

//获得手掌区域，最大连通域
IplImage *myGetClearPalmArea(IplImage *thImg)
{
	IplImage *tmpImg = cvCreateImage(cvGetSize(thImg), 8, 3);
	IplImage *outputImg = cvCloneImage(thImg);
	cvZero(tmpImg);

	int w = thImg->width;
	int h = thImg->height;
	CvMemStorage *storage = cvCreateMemStorage(0);
	CvSeq *contour = 0;

	//note: this function will change thImg
	int contour_num = cvFindContours(thImg, storage, &contour, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

	CvSeq *_contour = contour;
	double maxarea = 0;
	double minarea = w * h / 9;
	int m = 0;
	int maxIndex = 0;
	for (; contour != 0; contour = contour->h_next)
	{
		double tmparea = fabs(cvContourArea(contour));
		m++;
		if (tmparea < minarea)
		{
			continue;
		}
		if (tmparea > maxarea)
		{
			maxarea = tmparea;
			maxIndex = m - 1;
		}
	}

	CvScalar color = CV_RGB(0, 255, 255);
	contour = _contour;
	int count = 0;
	for (; contour != 0; contour = contour->h_next)
	{
		if (count == maxIndex)
		{
			CvScalar color = CV_RGB(255, 255, 255);
			cvDrawContours(tmpImg, contour, color, color, -1, -1, 8);
		}
		count++;
	}
	cvCvtColor(tmpImg, outputImg, CV_BGR2GRAY);

	cvReleaseMemStorage(&storage);
	cvReleaseImage(&tmpImg);

	return outputImg;
}